﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using FBroSharp;
using FBroSharp.Const;
using FBroSharp.DataType;
using FBroSharp.Event;
using FBroSharp.Lib;
using FBroSharp.Value;
using FBroSharp.Callback;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace BackgroundMouseAutomation
{
    public partial class Form1 : Form
    {
        private const string BROWSER_USER_FLAG = "slider_automation_browser";
        private IFBroSharpBrowser _browser;
        private bool _isSliding = false;

        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
            this.FormClosing += Form1_FormClosing;
            this.Resize += Form1_Resize;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            UpdateStatus("🔄 正在创建浏览器...");
            CreateBrowser();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            ResizeEmbeddedBrowser();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                if (_browser != null && _browser.IsValid)
                {
                    _browser.CloseBrowser(true, true);
                    _browser = null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"关闭浏览器失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 创建嵌入式浏览器
        /// </summary>
        private void CreateBrowser()
        {
            try
            {
                // 配置窗口信息
                FBroSharpWindowsInfo windowInfo = new FBroSharpWindowsInfo
                {
                    parent_window = panelBrowser.Handle, // 嵌入到Panel控件
                    x = 0,
                    y = 0,
                    width = panelBrowser.Width,
                    height = panelBrowser.Height,
                    window_name = "滑块自动化浏览器"
                };

                // 配置浏览器设置
                FBroSharpBrowserSetting settings = new FBroSharpBrowserSetting();

                // 创建浏览器事件处理器
                BrowserEvent browserEvent = new BrowserEvent(this);

                // 创建浏览器
                bool success = FBroSharpControl.CreatBrowser(
                    "file:///T:/html/slider/index.html",
                    windowInfo,
                    settings,
                    null, // request_context
                    null, // extra_info
                    browserEvent,
                    default, // event_control (struct类型使用default)
                    BROWSER_USER_FLAG
                );

                if (success)
                {
                    UpdateStatus("✅ 浏览器创建成功，等待页面加载...");
                    
                    // 异步获取浏览器实例
                    Task.Run(() =>
                    {
                        for (int i = 0; i < 50; i++) // 最多等待5秒
                        {
                            Thread.Sleep(100);
                            var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(BROWSER_USER_FLAG);
                            if (browser != null && browser.IsValid)
                            {
                                _browser = browser;
                                Console.WriteLine("✅ 成功获取浏览器实例");
                                break;
                            }
                        }
                    });
                }
                else
                {
                    UpdateStatus("❌ 浏览器创建失败");
                    MessageBox.Show("浏览器创建失败！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                UpdateStatus($"❌ 创建浏览器异常: {ex.Message}");
                MessageBox.Show($"创建浏览器异常: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 调整嵌入式浏览器大小
        /// </summary>
        private void ResizeEmbeddedBrowser()
        {
            try
            {
                if (_browser != null && _browser.IsValid)
                {
                    _browser.MoveWindow(0, 0, panelBrowser.Width, panelBrowser.Height, true);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"调整浏览器大小失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取滑块元素的坐标信息
        /// </summary>
        private async Task<(double handleX, double handleY, double holeX, double holeY, double distance)> GetSliderCoordinatesAsync()
        {
            return await Task.Run(() =>
            {
                try
                {
                    if (_browser == null || !_browser.IsValid)
                    {
                        throw new Exception("浏览器未就绪");
                    }

                    var frame = _browser.GetMainFrame();
                    if (frame == null)
                    {
                        throw new Exception("无法获取主框架");
                    }

                    // 执行JavaScript获取元素坐标
                    string script = @"
                        (function() {
                            const sliderHandle = document.getElementById('sliderHandle');
                            const targetHole = document.getElementById('targetHole');
                            
                            if (!sliderHandle || !targetHole) {
                                return JSON.stringify({ error: '未找到滑块或缺口元素' });
                            }
                            
                            const handleRect = sliderHandle.getBoundingClientRect();
                            const holeRect = targetHole.getBoundingClientRect();
                            
                            const result = {
                                handleCenterX: handleRect.x + handleRect.width / 2,
                                handleCenterY: handleRect.y + handleRect.height / 2,
                                holeCenterX: holeRect.x + holeRect.width / 2,
                                holeCenterY: holeRect.y + holeRect.height / 2,
                                distance: holeRect.x - handleRect.x
                            };
                            return JSON.stringify(result);
                        })();
                    ";

                    // 创建JS回调类
                    FBroSharpJsCallbackSyn callback = new FBroSharpJsCallbackSyn();

                    // 执行JavaScript并获取结果
                    frame.ExecuteJavaScriptToHasReturn(
                        script,
                        default,
                        default,
                        callback
                    );

                    // 等待结果（最多10秒）
                    if (callback.help != null && callback.help.IsValid)
                    {
                        callback.help.WaitEvent(10000);

                        if (callback.help.HavStringData())
                        {
                            string jsonData = callback.help.GetStringData();
                            callback.help.ClearData();

                            Console.WriteLine($"执行JS返回值: {jsonData}");

                            // 解析JSON结果
                            JObject json = JObject.Parse(jsonData);
                            
                            if (json["error"] != null)
                            {
                                throw new Exception(json["error"].ToString());
                            }

                            double handleX = json["handleCenterX"].Value<double>();
                            double handleY = json["handleCenterY"].Value<double>();
                            double holeX = json["holeCenterX"].Value<double>();
                            double holeY = json["holeCenterY"].Value<double>();
                            double distance = json["distance"].Value<double>();

                            Console.WriteLine($"📍 滑块坐标: ({handleX:F1}, {handleY:F1})");
                            Console.WriteLine($"📍 缺口坐标: ({holeX:F1}, {holeY:F1})");
                            Console.WriteLine($"📏 拖动距离: {distance:F1} 像素");

                            return (handleX, handleY, holeX, holeY, distance);
                        }
                        else
                        {
                            throw new Exception("JavaScript未返回字符串数据");
                        }
                    }
                    else
                    {
                        throw new Exception("JavaScript回调无效");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"❌ 获取坐标失败: {ex.Message}");
                    throw;
                }
            });
        }

        /// <summary>
        /// 方式1：普通拖动（直接拖动）
        /// </summary>
        private async void btnNormalDrag_Click(object sender, EventArgs e)
        {
            if (_isSliding)
            {
                MessageBox.Show("正在拖动中，请稍候...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            _isSliding = true;
            btnNormalDrag.Enabled = false;
            btnBezierDrag.Enabled = false;

            try
            {
                UpdateStatus("🎯 开始普通拖动滑块...");

                // 获取元素坐标
                var coords = await GetSliderCoordinatesAsync();

                // 等待一下让用户看到状态
                await Task.Delay(500);

                UpdateStatus($"📍 拖动距离: {coords.distance:F1} 像素");

                // 执行拖动操作
                bool success = await PerformVIPMouseDragAsync(
                    (int)coords.handleX,
                    (int)coords.handleY,
                    (int)coords.holeX,
                    (int)coords.handleY, // Y坐标保持不变，水平拖动
                    500 // 拖动延迟500ms
                );

                if (success)
                {
                    UpdateStatus("✅ 普通拖动完成！");
                    await Task.Delay(1000);
                    
                    // 检查验证结果
                    await CheckVerificationResultAsync();
                }
                else
                {
                    UpdateStatus("❌ 普通拖动失败");
                }
            }
            catch (Exception ex)
            {
                UpdateStatus($"❌ 拖动失败: {ex.Message}");
                MessageBox.Show($"拖动失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                _isSliding = false;
                btnNormalDrag.Enabled = true;
                btnBezierDrag.Enabled = true;
            }
        }

        /// <summary>
        /// 方式2：贝塞尔曲线拖动（模拟人为操作）
        /// </summary>
        private async void btnBezierDrag_Click(object sender, EventArgs e)
        {
            if (_isSliding)
            {
                MessageBox.Show("正在拖动中，请稍候...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            _isSliding = true;
            btnNormalDrag.Enabled = false;
            btnBezierDrag.Enabled = false;

            try
            {
                UpdateStatus("🎯 开始贝塞尔曲线拖动滑块...");

                // 获取元素坐标
                var coords = await GetSliderCoordinatesAsync();

                // 等待一下让用户看到状态
                await Task.Delay(500);

                UpdateStatus($"📍 拖动距离: {coords.distance:F1} 像素");

                // 生成贝塞尔曲线路径点
                List<Point> pathPoints = GenerateBezierCurvePath(
                    (int)coords.handleX,
                    (int)coords.handleY,
                    (int)coords.holeX,
                    (int)coords.handleY, // Y坐标保持不变，水平拖动
                    30 // 生成30个中间点
                );

                UpdateStatus($"🎨 生成了 {pathPoints.Count} 个路径点");

                // 执行贝塞尔曲线拖动
                bool success = await PerformBezierDragAsync(pathPoints);

                if (success)
                {
                    UpdateStatus("✅ 贝塞尔曲线拖动完成！");
                    await Task.Delay(1000);
                    
                    // 检查验证结果
                    await CheckVerificationResultAsync();
                }
                else
                {
                    UpdateStatus("❌ 贝塞尔曲线拖动失败");
                }
            }
            catch (Exception ex)
            {
                UpdateStatus($"❌ 拖动失败: {ex.Message}");
                MessageBox.Show($"拖动失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                _isSliding = false;
                btnNormalDrag.Enabled = true;
                btnBezierDrag.Enabled = true;
            }
        }

        /// <summary>
        /// 使用VIP鼠标控制执行拖动操作
        /// </summary>
        private async Task<bool> PerformVIPMouseDragAsync(int fromX, int fromY, int toX, int toY, int dragDelayMs = 200)
        {
            try
            {
                Console.WriteLine($"🖱️ VIP拖动: ({fromX}, {fromY}) → ({toX}, {toY})");

                if (_browser == null || !_browser.IsValid)
                {
                    return false;
                }

                // 使用VIP鼠标拖动功能（后台操作，不占用真实鼠标）
                using (var vipControl = _browser.GetVIPControl())
                {
                    var advanced = vipControl.GetAdvancedControl();

                    // 移动到起始位置
                    advanced.DispatchMouseMove(fromX, fromY);
                    await Task.Delay(100);

                    // 按下鼠标左键
                    advanced.DispatchMouseDown(fromX, fromY, 0); // 0 = 左键
                    await Task.Delay(100);

                    // 拖动到目标位置
                    advanced.DispatchMouseMove(toX, toY);
                    await Task.Delay(dragDelayMs);

                    // 释放鼠标左键
                    advanced.DispatchMouseUp(toX, toY, 0);
                }

                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ VIP拖动失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 生成贝塞尔曲线路径点
        /// </summary>
        private List<Point> GenerateBezierCurvePath(int startX, int startY, int endX, int endY, int pointCount)
        {
            List<Point> points = new List<Point>();
            
            // 计算控制点（模拟人为操作的轻微弧度）
            int distance = endX - startX;
            Random random = new Random();
            
            // 第一个控制点（上方偏移）
            int cp1X = startX + distance / 3;
            int cp1Y = startY - random.Next(5, 15); // 向上偏移5-15像素
            
            // 第二个控制点（下方偏移）
            int cp2X = startX + distance * 2 / 3;
            int cp2Y = startY + random.Next(5, 15); // 向下偏移5-15像素

            // 使用三次贝塞尔曲线公式生成路径点
            for (int i = 0; i <= pointCount; i++)
            {
                double t = (double)i / pointCount;
                
                // 三次贝塞尔曲线公式：B(t) = (1-t)³P₀ + 3(1-t)²tP₁ + 3(1-t)t²P₂ + t³P₃
                double x = Math.Pow(1 - t, 3) * startX +
                          3 * Math.Pow(1 - t, 2) * t * cp1X +
                          3 * (1 - t) * Math.Pow(t, 2) * cp2X +
                          Math.Pow(t, 3) * endX;
                
                double y = Math.Pow(1 - t, 3) * startY +
                          3 * Math.Pow(1 - t, 2) * t * cp1Y +
                          3 * (1 - t) * Math.Pow(t, 2) * cp2Y +
                          Math.Pow(t, 3) * endY;

                points.Add(new Point((int)x, (int)y));
            }

            Console.WriteLine($"🎨 贝塞尔曲线: 起点({startX},{startY}) 控制点1({cp1X},{cp1Y}) 控制点2({cp2X},{cp2Y}) 终点({endX},{endY})");
            
            return points;
        }

        /// <summary>
        /// 执行贝塞尔曲线拖动
        /// </summary>
        private async Task<bool> PerformBezierDragAsync(List<Point> pathPoints)
        {
            try
            {
                if (pathPoints.Count < 2 || _browser == null || !_browser.IsValid)
                {
                    return false;
                }

                Random random = new Random();

                using (var vipControl = _browser.GetVIPControl())
                {
                    var advanced = vipControl.GetAdvancedControl();

                    // 1. 移动到起点
                    Point startPoint = pathPoints[0];
                    advanced.DispatchMouseMove(startPoint.X, startPoint.Y);
                    await Task.Delay(50);

                    // 2. 按下鼠标左键
                    Console.WriteLine($"🖱️ 按下鼠标 at ({startPoint.X}, {startPoint.Y})");
                    advanced.DispatchMouseDown(startPoint.X, startPoint.Y, 0); // 0 = 左键
                    await Task.Delay(100);

                    // 3. 沿着贝塞尔曲线路径移动
                    for (int i = 1; i < pathPoints.Count; i++)
                    {
                        Point point = pathPoints[i];
                        
                        // 移动鼠标（保持按下状态）
                        advanced.DispatchMouseMove(point.X, point.Y);

                        // 随机延迟10-20ms，模拟人为速度
                        int delay = 10 + random.Next(10);
                        await Task.Delay(delay);
                        
                        if (i % 10 == 0)
                        {
                            Console.WriteLine($"🎯 移动中: ({point.X}, {point.Y}) [{i}/{pathPoints.Count}]");
                        }
                    }

                    // 4. 到达终点后稍作停留
                    await Task.Delay(100);

                    // 5. 释放鼠标左键
                    Point endPoint = pathPoints[pathPoints.Count - 1];
                    Console.WriteLine($"🖱️ 释放鼠标 at ({endPoint.X}, {endPoint.Y})");
                    advanced.DispatchMouseUp(endPoint.X, endPoint.Y, 0); // 0 = 左键
                }
                
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ 贝塞尔拖动失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 检查验证结果
        /// </summary>
        private async Task CheckVerificationResultAsync()
        {
            await Task.Run(() =>
            {
                try
                {
                    if (_browser == null || !_browser.IsValid)
                    {
                        return;
                    }

                    var frame = _browser.GetMainFrame();
                    if (frame == null)
                    {
                        return;
                    }

                    // 等待一下让页面更新
                    Thread.Sleep(500);

                    // 执行JavaScript检查验证状态
                    string script = @"
                        (function() {
                            const message = document.querySelector('.message');
                            if (message) {
                                return JSON.stringify({
                                    text: message.textContent,
                                    className: message.className
                                });
                            }
                            return JSON.stringify(null);
                        })();
                    ";

                    FBroSharpJsCallbackSyn callback = new FBroSharpJsCallbackSyn();

                    frame.ExecuteJavaScriptToHasReturn(
                        script,
                        default,
                        default,
                        callback
                    );

                    if (callback.help != null && callback.help.IsValid)
                    {
                        callback.help.WaitEvent(5000);

                        if (callback.help.HavStringData())
                        {
                            string jsonData = callback.help.GetStringData();
                            callback.help.ClearData();

                            if (!string.IsNullOrEmpty(jsonData) && jsonData != "null")
                            {
                                JObject json = JObject.Parse(jsonData);
                                string text = json["text"]?.ToString() ?? "";
                                string className = json["className"]?.ToString() ?? "";

                                if (className.Contains("success"))
                                {
                                    UpdateStatus($"🎉 {text}");
                                }
                                else if (className.Contains("error"))
                                {
                                    UpdateStatus($"❌ {text}");
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"❌ 检查结果失败: {ex.Message}");
                }
            });
        }

        /// <summary>
        /// 重置验证码
        /// </summary>
        private async void btnReset_Click(object sender, EventArgs e)
        {
            try
            {
                if (_browser == null || !_browser.IsValid)
                {
                    MessageBox.Show("浏览器未就绪", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                UpdateStatus("🔄 正在重置验证码...");

                await Task.Run(() =>
                {
                    var frame = _browser.GetMainFrame();
                    if (frame != null)
                    {
                        // 执行JavaScript点击重置按钮
                        string script = @"
                            (function() {
                                const resetBtn = document.querySelector('.reset-btn');
                                if (resetBtn) {
                                    resetBtn.click();
                                    return JSON.stringify(true);
                                }
                                return JSON.stringify(false);
                            })();
                        ";

                        FBroSharpJsCallbackSyn callback = new FBroSharpJsCallbackSyn();

                        frame.ExecuteJavaScriptToHasReturn(
                            script,
                            default,
                            default,
                            callback
                        );

                        if (callback.help != null && callback.help.IsValid)
                        {
                            callback.help.WaitEvent(5000);

                            if (callback.help.HavStringData())
                            {
                                string result = callback.help.GetStringData();
                                callback.help.ClearData();

                                if (result == "true")
                                {
                                    UpdateStatus("✅ 验证码已重置");
                                }
                            }
                        }
                    }
                });

                await Task.Delay(500);
            }
            catch (Exception ex)
            {
                UpdateStatus($"❌ 重置失败: {ex.Message}");
            }
        }

        #region UI更新方法（线程安全）

        public void UpdateStatus(string message)
        {
            if (InvokeRequired)
            {
                Invoke(new Action(() => UpdateStatus(message)));
                return;
            }

            lblStatus.Text = message;
            Console.WriteLine(message);
        }

        public void UpdateFormTitle(string title)
        {
            if (InvokeRequired)
            {
                Invoke(new Action(() => UpdateFormTitle(title)));
                return;
            }

            this.Text = $"后台鼠标自动化工具 - {title}";
        }

        public void EnableSliderButtons()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(EnableSliderButtons));
                return;
            }

            btnNormalDrag.Enabled = true;
            btnBezierDrag.Enabled = true;
            btnReset.Enabled = true;
        }

        #endregion
    }

    /// <summary>
    /// 同步 JavaScript 回调类
    /// 用于执行 JavaScript 并等待返回结果
    /// </summary>
    public class FBroSharpJsCallbackSyn : FBroSharpJsCallback
    {
        // 同步辅助类 - 用于线程同步等待
        public FBroSharpSynHelp help;
        
        public FBroSharpJsCallbackSyn()
        {
            // 初始化help类
            help = new FBroSharpSynHelp();
        }

        /// <summary>
        /// JavaScript 执行完成后的回调方法
        /// 根据返回类型保存数据到 help 中
        /// </summary>
        public override void Callback(FBroSharpJSRequestType type, IFBroSharpValue data, string error)
        {
            // 将返回的数据保存在help中
            if (help != null && help.IsValid)
            {
                switch (type)
                {
                    case FBroSharpJSRequestType.VALUE_ISVALID:
                        // 无效
                        help.SetStringData(error);
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_NULL:
                        // 空值
                        help.SetStringData("null");
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_INT:
                        // 整数值
                        help.SetIntData(data.GetInt());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_STRING:
                        // 文本值
                        help.SetStringData(data.GetString());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_BOOL:
                        // 逻辑值
                        help.SetBoolData(data.GetBool());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_DOUBLE:
                        // 双精度小数值
                        help.SetDoubleData(data.GetDouble());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_DATA_STRING:
                        // 时间文本值
                        help.SetStringData(data.GetString());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_ARRAY:
                        // 数组值
                        help.SetStringData(data.GetString());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_ARRAY_BUFFER:
                        // 数组缓存值
                        help.SetStringData(data.GetString());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_FUNCTION:
                        // 方法值
                        help.SetStringData(data.GetString());
                        break;
                        
                    case FBroSharpJSRequestType.VALUE_OBJECT:
                        // 对象值（JSON）
                        help.SetStringData(data.GetString());
                        break;
                }
                
                // 停止等待，唤醒主线程
                help.StopEvent();
            }
        }
    }
}
